﻿using FoundationLib.Ifc.DependencyInjection;
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FoundationLib.Common.DependencyInjection
{
	/// <summary>
	/// Represents a proxy for use with Enterprise Library Unity container.
	/// </summary>
	public abstract class UnityContainerProxy : IContainer
	{
		/// <summary>
		/// The underlying Unity container
		/// </summary>
		private IUnityContainer container;

		/// <summary>
		/// Creates a new <see cref="UnityContainerProxy"/> instance.
		/// </summary>
		protected UnityContainerProxy()
		{
		}

		/// <see cref="IContainer.Initialise()"/>
		public void Initialise()
		{
			if (this.container == null)
				this.container = new UnityContainer();
			this.Initialise(this.container);
		}

		/// <summary>
		/// Configures and initialises the container.
		/// </summary>
		/// <param name="container">The container</param>
		protected abstract void Initialise(IUnityContainer container);

		/// <see cref="IContainer.Resolve{T}()"/>
		public virtual T Resolve<T>()
		{
			return this.container.Resolve<T>();
		}

		/// <see cref="IContainer.Resolve{T}(string)"/>
		public virtual T Resolve<T>(string key)
		{
			return this.container.Resolve<T>(key);
		}

		/// <see cref="IContainer.Resolve{T}(object)"/>
		/// <remarks>This method is not supported by Unity, arguments are ignored.</remarks>
		public virtual T Resolve<T>(object arguments)
		{
			return this.Resolve<T>();
		}

		/// <see cref="IContainer.Resolve{T}(string, object)"/>
		/// <remarks>This method is not supported by Unity, arguments are ignored.</remarks>
		public virtual T Resolve<T>(string key, object arguments)
		{
			return this.Resolve<T>(key);
		}

		/// <see cref="IContainer.ResolveAll{T}()"/>
		public virtual T[] ResolveAll<T>()
		{
			return this.container.ResolveAll<T>().ToArray();
		}

		/// <see cref="IContainer.ResolveAll{T}(object)"/>
		/// <remarks>This method is not supported by Unity, arguments are ignored.</remarks>
		public virtual T[] ResolveAll<T>(object arguments)
		{
			return this.ResolveAll<T>();
		}

		/// <summary>
		/// Disposes of the instance and frees all resources.
		/// </summary>
		/// <param name="disposing">True if managed resources are to be freed</param>
		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				this.container.Dispose();
				this.container = null;
			}
		}

		/// <see cref="IDisposable.Dispose()"/>
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}
	}
}
